//
//  RCTBridge+SourceCode.m
//  LBReact
//
//  Created by WuShiHai on 19/6/17.
//  Copyright (c) 2019 Lebbay. All rights reserved.
//

#import "RCTBridge+SourceCode.h"

#import <LBFoundation/LBFoundation.h>
#import <React/RCTUtils.h>

#import <objc/runtime.h>

#import "LBRViewController.h"
#import "LBReactBridge+Util.h"

@implementation RCTBridge(SourceCode)

- (void)executeSourceCodeIn:(NSString *)folderPath
                     module:(NSString *)module {
    NSLog(@"executeSourceCodeIn: %@----%@", self, folderPath);
    NSAssert([self.batchedBridge isKindOfClass:[RCTCxxBridge class]], @"batchedBridge 应为 RCTCxxBridge子类");
    NSError *error = nil;
    NSData *sourceCode = [NSData dataWithContentsOfFile:[LBReactBridge pathOfJSBundleIn:folderPath]
                                                options:NSDataReadingMappedIfSafe
                                                 error:&error];
    if (error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification
                                                                object:nil];
        });
    } else {
        [self executeSourceCode:sourceCode
                         module:module];
    }
}

- (void)executeSourceCode:(NSData *)sourceCode
                   module:(NSString *)module {
    
    NSAssert([self.batchedBridge isKindOfClass:[RCTCxxBridge class]], @"batchedBridge 应为 RCTCxxBridge子类");
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:LBJavaScriptWillStartLoadingModuleNotification
                                                            object:module];
    });
    [(RCTCxxBridge *)self.batchedBridge executeSourceCode:sourceCode
                                                     sync:NO
                                                   module:module];
}

//- (BOOL)isExecute:(NSString *)module {
//    NSAssert([self.batchedBridge isKindOfClass:[RCTCxxBridge class]], @"batchedBridge 应为 RCTCxxBridge子类");
//    return [[(RCTCxxBridge *)self.batchedBridge moduleNames] containsObject:module];
//}

@end

@implementation RCTCxxBridge(SourceCode)

+ (void)load {
    RCTSwapInstanceMethods([RCTCxxBridge class],
                           @selector(enqueueApplicationScript:url:onComplete:),
                           @selector(lb_enqueueApplicationScript:url:onComplete:));
}

- (void)executeSourceCode:(NSData *)sourceCode
                     sync:(BOOL)sync
                   module:(NSString *)module {
    [self setRunModuleName:module];
    [self executeSourceCode:sourceCode
                       sync:sync];
    [self setRunModuleName:nil];
}

- (void)lb_enqueueApplicationScript:(NSData *)script
                                url:(NSURL *)url
                         onComplete:(dispatch_block_t)onComplete {
    
    NSString *module = [self runModuleName];
    dispatch_block_t completion = ^{
        if (onComplete) {
            onComplete();
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            //module 为空 则为主包加载
//            if (module && [[self moduleNames] containsObject:module] == NO) {
//                [[self moduleNames] addObject:module];
//            }
            
            [[NSNotificationCenter defaultCenter] postNotificationName:LBJavaScriptDidLoadingModuleNotification
                                                                object:module];
        });
    };
    [self lb_enqueueApplicationScript:script
                                  url:url
                           onComplete:completion];
}

- (NSString *)runModuleName {
    return objc_getAssociatedObject(self, @selector(runModuleName));
}

- (void)setRunModuleName:(NSString *)name {
    objc_setAssociatedObject(self, @selector(runModuleName), name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

//- (NSMutableArray<NSString *> *)moduleNames {
//    static dispatch_once_t onceToken;
//    static NSMutableArray<NSString *> *moduleNames = nil;
//    dispatch_once(&onceToken, ^{
//        moduleNames = [@[] mutableCopy];
//    });
//    return moduleNames;
//}

@end
